﻿//========================================================= 
/**@file JavaITransceiveTransInvoker.h
 * @brief 回调Java类实现 ITransceiveTrans 接口的封装类
 *
 * class XXInvoker {
        public native boolean TransCommand(byte[] sCmd, int sLen, byte[] rCmd, int[] rLen);
    }
 *
 * 
 * @date 2018-07-28   09:29:56
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_JAVAITRANSCEIVETRANSINVOKER_H_
#define _LIBZHOUYB_JAVAITRANSCEIVETRANSINVOKER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"
#include "../../include/BaseDevice.h"

#include "JniInvoker.h"
//--------------------------------------------------------- 
namespace zhou_yb {
namespace extension {
namespace ability {
//--------------------------------------------------------- 
/// 回调Java类实现IInteractiveTrans接口的封装类(建议当作局部变量来使用)
class JavaITransceiveTransInvoker :
    public ITransceiveTrans,
    public DeviceBehavior,
    public RefObject
{
protected:
    ByteBuilder _tmpBuffer;

    /// Java类的回调函数
    jmethodID _callback;
    /// Jni对象
    JniInvoker _jniInvoker;
    /// 发送缓冲区
    jbyteArray _sendArray;
    /// 接收缓冲区
    jbyteArray _recvArray;
    /// 接收长度
    jintArray _recvLenArray;

    /// 初始化
    inline void _init()
    {
        _callback = NULL;

        _sendArray = NULL;
        _recvArray = NULL;
        _recvLenArray = NULL;
    }
public:
    JavaITransceiveTransInvoker()
    {
        _init();
    }
    virtual ~JavaITransceiveTransInvoker()
    {
        Dispose();
    }
    /// 创建引用
    bool Create(JniInvoker& jniInvoker, size_t arraySize = DEV_BUFFER_SIZE)
    {
        LOG_FUNC_NAME();
        ASSERT_DeviceValid(jniInvoker.IsValid());

        LOGGER(_log.WriteLine("GetMethodID..."));
        jmethodID callMethod = jniInvoker->GetMethodID(jniInvoker, "TransCommand", "([BI[B[I)Z");
        LOGGER(_log << "CallMethod:<" << _hex(callMethod) << ">\n");
        if(callMethod == NULL)
        {
            _logErr(DeviceError::OperatorStatusErr, "回调指针为NULL");
            return _logRetValue(false);
        }

        LOGGER(_log.WriteLine("GetArray..."));
        jbyteArray sendArray = jniInvoker->NewByteArray(arraySize);
        jbyteArray recvArray = jniInvoker->NewByteArray(arraySize);
        jintArray recvLenArray = jniInvoker->NewIntArray(2);
        LOGGER(_log << "SendArray:<" << _hex(sendArray) << ">\n");
        LOGGER(_log << "RecvArray:<" << _hex(recvArray) << ">\n");
        LOGGER(_log << "RecvLenArray:<" << _hex(recvLenArray) << ">\n");
        if(sendArray == NULL || recvArray == NULL || recvLenArray == NULL)
        {
            if(sendArray) jniInvoker->DeleteLocalRef(sendArray);
            if(recvArray) jniInvoker->DeleteLocalRef(recvArray);
            if(recvLenArray) jniInvoker->DeleteLocalRef(recvLenArray);

            _logErr(DeviceError::OperatorStatusErr, "申请缓冲区失败");
            return _logRetValue(false);
        }

        Dispose();

        _jniInvoker = jniInvoker;
        _callback = callMethod;

        _sendArray = sendArray;
        _recvArray = recvArray;
        _recvLenArray = recvLenArray;

        return _logRetValue(true);
    }
    /// 返回对象是否有效
    inline bool IsValid() const
    {
        return _jniInvoker.IsValid();
    }
    /// 释放相关资源
    void Dispose()
    {
        LOG_FUNC_NAME();
        if(IsValid())
        {
            LOGGER(_log.WriteLine("DeleteLocalRef..."));
            if(_sendArray != NULL)
                _jniInvoker->DeleteLocalRef(_sendArray);
            if(_recvArray != NULL)
                _jniInvoker->DeleteLocalRef(_recvArray);
            if(_recvLenArray != NULL)
                _jniInvoker->DeleteLocalRef(_recvLenArray);
            _jniInvoker.Dispose();

            _init();
        }
        LOGGER(_logRetValue(true));
    }
    /// 交换数据
    virtual bool TransCommand(const ByteArray& send, ByteBuilder& recv)
    {
        LOG_FUNC_NAME();
        ASSERT_Device();
        LOGGER(_log.WriteLine("SEND:").WriteLine(send));
        LOGGER(size_t lastLen = recv.GetLength());

        JniConverter(_jniInvoker).set_jbyteArray(send, _sendArray);
        jvalue args[4];
        args[0].l = _sendArray;
        args[1].i = send.GetLength();
        args[2].l = _recvArray;
        args[3].l = _recvLenArray;

        jobject jObj = _jniInvoker;
        jboolean bRet = _jniInvoker->CallBooleanMethodA(jObj, _callback, args);
        ASSERT_FuncErrRet(bRet == JNI_TRUE, DeviceError::TransceiveErr);

        jint buf[2];
        _jniInvoker->GetIntArrayRegion(_recvLenArray, 0, 2, buf);
        JniConverter(_jniInvoker).get_jbyteArray(_recvArray, buf[0], recv);

        LOGGER(_log.WriteLine("RECV:").WriteLine(recv.SubArray(lastLen)));
        return _logRetValue(true);
    }
};
//--------------------------------------------------------- 
} // namespace ability 
} // namespace extension 
} // namespace zhou_yb
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_JAVAITRANSCEIVETRANSINVOKER_H_
//========================================================= 